From: kfraser@localhost.localdomain Date: Fri, 28 Jul 2006 15:53:58 +0000 (+0100) Subject: Merge. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15777 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=30ec81982666ed3db0e2ad0ea98252e6e4b1a2dd;p=xen.git Merge. --- diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 05b876e93c..1db6bbc9d7 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -99,17 +99,17 @@ struct netfront_info { struct timer_list rx_refill_timer; /* - * {tx,rx}_skbs store outstanding skbuffs. The first entry in each - * array is an index into a chain of free entries. + * {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs + * is an index into a chain of free entries. */ struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1]; - struct sk_buff *rx_skbs[NET_RX_RING_SIZE+1]; + struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; #define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) grant_ref_t gref_tx_head; grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1]; grant_ref_t gref_rx_head; - grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1]; + grant_ref_t grant_rx_ref[NET_TX_RING_SIZE]; struct xenbus_device *xbdev; int tx_ring_ref; @@ -122,7 +122,7 @@ struct netfront_info { }; /* - * Access macros for acquiring freeing slots in {tx,rx}_skbs[]. + * Access macros for acquiring freeing slots in tx_skbs[]. */ static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id) @@ -138,6 +138,29 @@ static inline unsigned short get_id_from_freelist(struct sk_buff **list) return id; } +static inline int xennet_rxidx(RING_IDX idx) +{ + return idx & (NET_RX_RING_SIZE - 1); +} + +static inline struct sk_buff *xennet_get_rx_skb(struct netfront_info *np, + RING_IDX ri) +{ + int i = xennet_rxidx(ri); + struct sk_buff *skb = np->rx_skbs[i]; + np->rx_skbs[i] = NULL; + return skb; +} + +static inline grant_ref_t xennet_get_rx_ref(struct netfront_info *np, + RING_IDX ri) +{ + int i = xennet_rxidx(ri); + grant_ref_t ref = np->grant_rx_ref[i]; + np->grant_rx_ref[i] = GRANT_INVALID_REF; + return ref; +} + #define DPRINTK(fmt, args...) \ pr_debug("netfront (%s:%d) " fmt, \ __FUNCTION__, __LINE__, ##args) @@ -598,8 +621,9 @@ static void network_alloc_rx_buffers(struct net_device *dev) skb->dev = dev; - id = get_id_from_freelist(np->rx_skbs); + id = xennet_rxidx(req_prod + i); + BUG_ON(np->rx_skbs[id]); np->rx_skbs[id] = skb; RING_GET_REQUEST(&np->rx, req_prod + i)->id = id; @@ -840,6 +864,19 @@ static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) return IRQ_HANDLED; } +static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb, + grant_ref_t ref) +{ + int new = xennet_rxidx(np->rx.req_prod_pvt); + + BUG_ON(np->rx_skbs[new]); + np->rx_skbs[new] = skb; + np->grant_rx_ref[new] = ref; + RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new; + RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref; + np->rx.req_prod_pvt++; + RING_PUSH_REQUESTS(&np->rx); +} static int netif_poll(struct net_device *dev, int *pbudget) { @@ -874,12 +911,15 @@ static int netif_poll(struct net_device *dev, int *pbudget) i++, work_done++) { rx = RING_GET_RESPONSE(&np->rx, i); + skb = xennet_get_rx_skb(np, i); + ref = xennet_get_rx_ref(np, i); + /* * This definitely indicates a bug, either in this driver or in * the backend driver. In future this should flag the bad * situation to the system controller to reboot the backed. */ - if ((ref = np->grant_rx_ref[rx->id]) == GRANT_INVALID_REF) { + if (ref == GRANT_INVALID_REF) { WPRINTK("Bad rx response id %d.\n", rx->id); work_done--; continue; @@ -890,21 +930,12 @@ static int netif_poll(struct net_device *dev, int *pbudget) if (net_ratelimit()) WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n", rx->id, rx->status); - RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = - rx->id; - RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = - ref; - np->rx.req_prod_pvt++; - RING_PUSH_REQUESTS(&np->rx); + xennet_move_rx_slot(np, skb, ref); work_done--; continue; } gnttab_release_grant_reference(&np->gref_rx_head, ref); - np->grant_rx_ref[rx->id] = GRANT_INVALID_REF; - - skb = np->rx_skbs[rx->id]; - add_id_to_freelist(np->rx_skbs, rx->id); /* NB. We handle skb overflow later. */ skb->data = skb->head + rx->offset; @@ -1158,15 +1189,23 @@ static void network_connect(struct net_device *dev) } /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */ - for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) { - if ((unsigned long)np->rx_skbs[i] < PAGE_OFFSET) + for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) { + if (!np->rx_skbs[i]) continue; + gnttab_grant_foreign_transfer_ref( np->grant_rx_ref[i], np->xbdev->otherend_id, __pa(np->rx_skbs[i]->data) >> PAGE_SHIFT); RING_GET_REQUEST(&np->rx, requeue_idx)->gref = np->grant_rx_ref[i]; - RING_GET_REQUEST(&np->rx, requeue_idx)->id = i; + RING_GET_REQUEST(&np->rx, requeue_idx)->id = requeue_idx; + + if (requeue_idx < i) { + np->rx_skbs[requeue_idx] = np->rx_skbs[i]; + np->grant_rx_ref[requeue_idx] = np->grant_rx_ref[i]; + np->rx_skbs[i] = NULL; + np->grant_rx_ref[i] = GRANT_INVALID_REF; + } requeue_idx++; } @@ -1392,8 +1431,8 @@ static struct net_device * __devinit create_netdev(int handle, np->grant_tx_ref[i] = GRANT_INVALID_REF; } - for (i = 0; i <= NET_RX_RING_SIZE; i++) { - np->rx_skbs[i] = (void *)((unsigned long) i+1); + for (i = 0; i < NET_RX_RING_SIZE; i++) { + np->rx_skbs[i] = NULL; np->grant_rx_ref[i] = GRANT_INVALID_REF; }